from django.shortcuts import render
from web.forms.file import FolderModelForm, FileModelForm
from django.http import JsonResponse, HttpResponse
from web import models
from django.forms import model_to_dict
from utils.tencent.cos import delete_file, delete_file_list, credential
from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse
from django.utils.encoding import escape_uri_path
import json
import requests


def file(request, project_id):
    parent_object = None
    folder_id = request.GET.get('folder', "")  # 如果在路径里面带有这个folder或者为空
    if folder_id.isdecimal():
        parent_object = models.FileRepository.objects.filter(id=int(folder_id), file_type=2,
                                                             project=request.tracer.project).first()
    """文件列表&&添加文件夹"""
    if request.method == "GET":
        # 导航栏的编写，一层一层的找下去
        breadcrumb_list = []
        parent = parent_object
        while parent:
            # breadcrumb_list.insert(0, {'id': parent.id, 'name': parent.name})
            breadcrumb_list.insert(0, model_to_dict(parent, ['id', 'name']))
            parent = parent.parent
        """显示文件夹"""
        queryset = models.FileRepository.objects.filter(project_id=request.tracer.project)
        if parent_object:
            file_object_list = queryset.filter(parent=parent_object).order_by("-file_type")
        else:
            file_object_list = queryset.filter(parent__isnull=True).order_by("-file_type")
        form = FolderModelForm(request, parent_object)
        web_js_content = {
            'form': form,
            'file_object_list': file_object_list,
            'breadcrumb_list': breadcrumb_list,
            'folder_object': parent_object,
        }
        return render(request, 'personal_management/file.html', web_js_content)
    """添加文件夹"""
    fid = request.POST.get('fid', '')
    edit_object = None
    if fid.isdecimal():
        edit_object = models.FileRepository.objects.filter(id=int(fid), file_type=2,
                                                           project=request.tracer.project).first()
    # 这里出现了一个错误'QuerySet' object has no attribute '_meta'，解决的方法对象列表没有'_meta'属性，单独的对象才有
    if edit_object:
        form = FolderModelForm(request, parent_object, data=request.POST, instance=edit_object)
    else:
        form = FolderModelForm(request, parent_object, data=request.POST)
    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.file_type = 2
        form.instance.update_user = request.tracer.user
        form.instance.parent = parent_object
        form.save()
        return JsonResponse({'status': True})
    return JsonResponse({'status': False, 'error': form.errors})


# 删除文件夹
def file_delete(request, project_id):
    fid = request.GET.get('fid')
    # 删除数据库中的 文件夹 & 文件(级联删除)
    delete_object = models.FileRepository.objects.filter(id=fid, project=request.tracer.project).first()
    if delete_object.file_type == 1:
        # 删除文件（数据库中删除这个文件，cos中删除文件，释放项目已使用的空间）
        # 释放空间
        request.tracer.project.user_space -= delete_object.file_size
        # 保存数据库
        request.tracer.project.save()
        # 从cos中单个删除文件
        delete_file(request.tracer.project.bucket, request.tracer.project.region, delete_object.key)
        # 数据库中和删除
        delete_object.delete()

        return JsonResponse({'status': True})
    # 删除文件夹（找到这个文件夹下面的所有文件数据库删除，cos中删除文件，释放项目已使用的空间）

    total_size = 0
    key_list = []
    folder_list = [delete_object, ]
    for folder in folder_list:
        child_list = models.FileRepository.objects.filter(project=request.tracer.project, parent=folder).order_by(
            '-file_type')
        for child in child_list:
            if child.file_type == 2:
                folder_list.append(child)
            else:
                total_size += child.file_size
                # 批量删除
                key_list.append({'key': child.key})
    # cos批量删除图片
    if key_list:
        delete_file_list(request.tracer.project.bucket, request.tracer.project.region, key_list)

    if total_size:
        request.tracer.project.user_space -= total_size
        # 保存数据库
        request.tracer.project.save()
    delete_object.delete()
    return JsonResponse({'status': True})


# 获取临时凭证
@csrf_exempt
def cos_credentials(request, project_id):
    # 换算成M
    file_size_limit = request.tracer.price_policy.file_size * 1024 * 1024
    # 换算成G
    total_file_limit = request.tracer.price_policy.p_space * 1024 * 1024 * 1024

    total_size = 0
    # 通过body获取传过来的所有文件数据，由于从前端穿过来的数据全是乱码状态，所以要解码，然后转换成json格式
    info = json.loads(request.body.decode('utf-8'))
    # 最后在后端进行数据的判断那些该上传，那些该拦截，并且把错误的数据放到error里面，通过modalForm渲染给前端
    # 不管数据有没有在我的限制范围内，我们都要给前端传递我们的状态status，False or True
    # 记得把文件大小转换成M，由于我们传递过来的是字节
    for item in info:
        # 文件超出限制，转化成 B字节
        if item['size'] > file_size_limit:
            msg = "单文件超出最大的限制(最大{}M)，文件:{},请升级套餐.".format(request.tracer.price_policy.file_size, item['name'])

            return JsonResponse({'status': False, 'error': msg})
        total_size += item['size']
        # 做容量限制：单文件 & 总容量
    # 总容量限制限制
    if request.tracer.project.user_space + total_size > total_file_limit:
        JsonResponse({'status': False, 'error': "容量超出限制，请升级套餐。"})
    # 获取临时凭证
    data_dic = credential(request.tracer.project.bucket, request.tracer.project.region)
    return JsonResponse({'status': True, 'data': data_dic})


@csrf_exempt
def file_post(request, project_id):
    form = FileModelForm(request, data=request.POST)
    if form.is_valid():
        data_dic = form.cleaned_data
        data_dic.pop('etag')
        data_dic.update({'project': request.tracer.project, 'file_type': 1, 'update_user': request.tracer.user})
        instance = models.FileRepository.objects.create(**data_dic)
        # 把已使用过的空间和这个文件大小增加
        request.tracer.project.user_space += data_dic['file_size']
        request.tracer.project.save()
        # 传递到前端写入到页面
        result = {
            'fid': instance.id,
            'name': instance.name,
            'file_type': instance.get_file_type_display(),
            'file_size': instance.file_size,
            'update_user': instance.update_user.username,
            'datetime': instance.update_datetime.strftime("%Y年%m月%d日 %H:%m"),
            'download_url': reverse('websass:file_download',
                                    kwargs=({'project_id': project_id, 'file_id': instance.id}))
        }
        return JsonResponse({'status': True, 'data': result})
    return JsonResponse({'status': False, 'data': form.errors})


# 下载文件视图
def file_download(request, project_id, file_id):
    """下载文件"""
    # 文件内容
    # 设置响应头
    # 打开文件，获取文件内容，从cos中打开文件，远程打开文件
    file_object = models.FileRepository.objects.filter(id=file_id, project_id=project_id).first()
    file_url = requests.get(file_object.file_path)
    data = file_url.iter_content()
    response = HttpResponse(data, content_type='application/octet-stream')
    response['Content-Disposition'] = "attachment; filename={};".format(escape_uri_path(file_object.name))

    return response
